﻿<?php
# http://projects:8081/cdapp-2kt-api/api/flow_ntfm_load.php

include_once '_portal.php';
// 流量快照
include_once 'flow_ntfm_load_snapshot.php';

const REQUEST_CONTENT_EXAMPLE_FILE_PATH = './flow_ntfm_load_example_raw_request.json';
const REQUEST_RESPONSE_EXAMPLE_FILE_PATH = './flow_ntfm_load_example_raw_response.json';
const NTFM_API_URL = 'http://10.202.91.233:2333/NTFM-FORE/forecast/sect/queryClassifyFlow';
const DURATION_HOURS_PASSED = 6;
const DURATION_HOURS_PASSED_DISPOSED = 1;
const DURATION_HOURS = 48;
const STEP_MINUTES = 15;
// const HISTORY_LOCK_HOURS = 12;
const HISTORY_LOCK_MOMENT = '04:00:00';
const LOAD_FAKE_RESPONSE = false;
const MIN_TTL = 1 * 60 * 1000; # unit: ms
const MAX_TTL = 5 * 60 * 1000; # unit: ms
const PARAM_NAME = 'flowRefreshTime';
const PARAM_NAME_VERSION = 'flowDataVersion';

$force = isset($_GET['force']) ? $_GET['force'] : 0;
$ignore = isset($_GET['ignore']) ? $_GET['ignore'] : 0;

// terminate request SIPDS
if (get_variable('STOP_ALL_NETWORK') === 1) {
  die('Network Stoped');
}
if (get_variable('STOP_NTFM') === 1) {
  die('NTFM Stoped');
}

output(main($force, $ignore));

die();

function main($force = 0, $ignore = 0) {
  # refresh information
  $refresh_info = get_param(PARAM_NAME);
  $ttl_verify = verify_ttl($refresh_info['tx'], $refresh_info['rx'], MIN_TTL, MAX_TTL);
  $info = 'flow_ntfm_load: ' . $ttl_verify['info'];
  $status = $ttl_verify['status'];
  # need for refresh
  if ($status > 0 || $force > 0) {
    $time_tx = timestamp();
    $time_rx = $refresh_info['rx'];
    save_param(PARAM_NAME, ['tx' => $time_tx, 'rx' => $time_rx]);
    $response_full = request_ntfm();
    $response = $response_full['response'];
    $result = fetch_response($response, $ignore);
    $time_rx = timestamp();
    $duration = $time_rx - $time_tx;
    $successed = $result['countCell'] > 0 && $result['requestStatus'] && $result['fetchStatus'];
    // 不论是否更新成功, 更新流量快照 @2024/03/12
    makeSnap();
    if ($successed) {
      save_param(PARAM_NAME, ['tx' => $time_tx, 'rx' => $time_rx]);
      save_param(PARAM_NAME_VERSION, ['value' => date('Y-m-d H:i:s')]);
    }
    return [
      'message' => $force > 0 ? 'Forced to refresh NTFM data manually' : $info,
      'successed' => $successed,
      'modifiers' => ['force' => $force, 'ignore' => $ignore],
      'duration' => $duration,
      'result' => $result,
      // 'response' => $response,
      // 'fullResponse' => $response_full,
    ];
  } else {
    return [
      'message' => $info,
      'successed' => false,
      'duration' => 0,
      'result' => null,
      // 'response' => null,
      // 'fullResponse' => null,
    ];
  }

}

function fetch_response($response, $ignore = 0) {
  if (!$response || $response == null || !isset($response)) {
    $result_ext = update_details();
    # 无 NTFM_response 的情况
    return [
      'requestDuration' => 0,
      'requestStatus' => false,
      'fetchDuration' => 0,
      'fetchStatus' => false,
      'detailsStatus' => $result_ext,
      'countCell' => 0,
      'countLine' => 0,
      'rawData' => [],
    ];
  }
  $all_zero = true;
  $timestamp = timestamp();
  $step = $response['info']['step'];
  $begTime = $response['info']['begTime'];
  $endTime = $response['info']['endTime'];
  $count = floor((strtotime($endTime) - strtotime($begTime)) / ($step * 60)) + 1;
  $keys = explode(':', $response['info']['payload']['key']);
  $data = $response['data'];
  $sql = "INSERT INTO `2kt_flow_record`(`moment`, `content`, `history`) VALUES ";
  $output = [];
  $dataCount = 0;
  # dispose first several cells due to bugs of NTFM
  $startIndex = DURATION_HOURS_PASSED_DISPOSED * round(60 / STEP_MINUTES); // STEP_MINUTES or $step
  for ($i = $startIndex; $i < $count; $i++) {
    $moment = date('Y-m-d H:i:s', strtotime($begTime) + $i * $step * 60);
    $content = [];
    foreach ($keys as $label) {
      $value = $data[$label][$i];
      $content[] = ($label == 'other' && $ignore) ? 0 : $value;
      // $content[] = $value;
      $dataCount++;
      $all_zero = $all_zero && ($value == 0 || $value == '0' || $value == null);
    }
    $output[] = ['moment' => $moment, 'content' => $content];
    $content_json = json_stringify($content);
    $sql .= "('{$moment}','{$content_json}','{$content_json}'),";
  }
  if ($all_zero) {
    $result_ext = update_details();
    # NTFM_response 全0的情况
    return [
      // 'tags' => $tags,
       'requestDuration' => $response['info']['duration'],
      'requestStatus' => false,
      'fetchDuration' => timestamp() - $timestamp,
      'fetchStatus' => false,
      'detailsStatus' => $result_ext,
      'countCell' => $dataCount,
      'countLine' => $count,
      'rawData' => $output,
      // 'sql' => $sql,
    ];
  } else {
    $sql = rtrim($sql, ',');
    $updated = date('Y-m-d H:i:s');
    $sql .= " ON DUPLICATE KEY UPDATE `content` = VALUES(`content`),`updated` = '{$updated}'";
    $result = exec_sql($sql);
    $result_ext = update_details();
    $result_his = update_history();
    # NTFM_response 正常的情况
    return [
      // 'tags' => $tags,
       'requestDuration' => $response['info']['duration'],
      'requestStatus' => true,
      'fetchDuration' => timestamp() - $timestamp,
      'fetchStatus' => $result,
      'detailsStatus' => $result_ext,
      'historyStatus' => $result_his,
      'countCell' => $dataCount,
      'countLine' => $count,
      'rawData' => $output,
      // 'sql' => $sql,
    ];
  }
}

function request_ntfm() {
  $timestamp = timestamp();
  $payload = json_parse(file_get_contents(REQUEST_CONTENT_EXAMPLE_FILE_PATH));
  $info = [];
  $info['step'] = $payload['step'] = STEP_MINUTES;
  $info['begTime'] = $payload['begTime'] = date('Y-m-d H', time() - 3600 * DURATION_HOURS_PASSED) . ':00:00';
  $info['endTime'] = $payload['endTime'] = date('Y-m-d H', time() + 3600 * DURATION_HOURS) . ':00:00';
  $info['tags'] = explode(':', $payload['key']);
  $info['payload'] = $payload;
  $response_raw = null;
  $response = null;
  if (LOAD_FAKE_RESPONSE) {
    $response = file_get_contents(REQUEST_RESPONSE_EXAMPLE_FILE_PATH);
  } else {
    $curl = curl_init();
    curl_setopt_array($curl, array(
      CURLOPT_URL => NTFM_API_URL,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_ENCODING => '',
      CURLOPT_MAXREDIRS => 10,
      CURLOPT_TIMEOUT => 60,
      CURLOPT_FOLLOWLOCATION => true,
      CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
      CURLOPT_CUSTOMREQUEST => 'POST',
      CURLOPT_POSTFIELDS => json_stringify($payload),
      CURLOPT_HTTPHEADER => array(
        'Content-Type: application/json',
      ),
    ));
    $response_raw = $response = curl_exec($curl);
    curl_close($curl);
    // echo $response;
  }
  if ($response != null && $response != '' && $response) {
    $res_object = json_parse($response);
    if (gettype($res_object) != 'array') {return null;}
    $info['duration'] = timestamp() - $timestamp;
    $res_object['info'] = $info;
    $res_object['status'] = true;
    return [
      'response' => $res_object,
      'info' => $info,
      'payload' => $payload,
      'raw' => $response_raw,
    ];
  } else {
    return [
      'response' => null,
      'info' => $info,
      'payload' => $payload,
      'raw' => $response_raw,
    ];
  }
}

function update_history() {
  # Update history data
  // obsolete computing for history threshold
  // $history_threshold = date('Y-m-d H:i:s', time() + HISTORY_LOCK_HOURS + 3600);
  # 每日0400前更新当日0400含以后的计划架次，0400后更新次日计划架次
  $history_threshold = date('Y-m-d') . ' ' . HISTORY_LOCK_MOMENT;
  if (time() > strtotime($history_threshold)) {
    $history_threshold = date('Y-m-d', strtotime("tomorrow")) . ' ' . HISTORY_LOCK_MOMENT;
  }
  $sql_his = "UPDATE `2kt_flow_record` SET `history`=`content` WHERE `moment` >= '{$history_threshold}'";
  $result_his = exec_sql($sql_his);
  return $result_his;
}

function update_details() {
  $minute = (int)date('i');
  $minute = $minute < 15 ? 0 : (($minute < 30 ? 15 : ($minute < 45 ? 30 : 45)));
  $moment = date('Y-m-d H:') . $minute . ':00';
  $sector = 0;
  $mode = 'NN';
  $details = [
    'direction' => [
      'ZUUU' => 'N',
      'ZUTF' => 'N',
    ],
    'activity' => [],
    'seats' => [],
    'users' => [],
    'supervisors' => [],
  ];

  # sector, seats, seats
  $sql = "SELECT `seatName`,  `sectorCodes`, `users` FROM `2kt_seat_status` WHERE `seatType` = '普通管制'";
  $res = query_parse(exec_sql($sql));
  foreach ($res as $cell) {
    if ($cell['sectorCodes'] && count($cell['sectorCodes']) > 0) {
      $sector++;
      $details['seats'][$cell['seatName']] = $cell['sectorCodes'];
      $details['users'][$cell['seatName']] = [];
      foreach ($cell['users'] as $user) {
        $details['users'][$cell['seatName']][] = $user['userName'];
      }
    }
  }

  # supervisor
  $sql = "SELECT `seatName`, `users` FROM `2kt_seat_status` WHERE `seatName` LIKE '%SUP%' OR `seatName` LIKE '%OMA%';";
  $res = query_parse(exec_sql($sql));
  foreach ($res as $cell) {
    $details['supervisors'][$cell['seatName']] = [];
    foreach ($cell['users'] as $user) {
      if ($user['seatRole'] == '管制' || $user['seatRole'] == '教员') {
        $details['supervisors'][$cell['seatName']][] = $user['userName'];
      }
    }
  }

  # dierction
  $sql = "SELECT `seatPostList`,  `logicSectorCode` FROM `2kt_seat_status` WHERE `seatType` = '运行方向'";
  $res = query_parse(exec_sql($sql));
  $mode = $res ? $res[0]['logicSectorCode'] : 'NN';
  $details['direction']['ZUUU'] = $res ? $res[0]['seatPostList']['ZUUU'] : 'N';
  $details['direction']['ZUTF'] = $res ? $res[0]['seatPostList']['ZUTF'] : 'N';

  #activity
  $sql = "SELECT DISTINCT `arrField`, `depField` FROM `2kt_activity_military`";
  $res = exec_sql($sql);
  if ($res) {
    foreach ($res as $cell) {
      if (!in_array($cell['arrField'], $details['activity'])) {
        $details['activity'][] = $cell['arrField'];
      }
      if (!in_array($cell['depField'], $details['activity'])) {
        $details['activity'][] = $cell['depField'];
      }
      if (($cell['depField'] == '温江' || $cell['depField'] == '温江') && strlen($mode) == 2) {
        $mode .= 'WJ';
      }
    }
  }

  # update data
  $details = json_stringify($details);
  $sql = "UPDATE `2kt_flow_record` SET `sector`={$sector},`mode`='{$mode}',`details`='{$details}' WHERE `moment`='{$moment}'";
  return exec_sql($sql);
}